﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechnicalAnalysisEngine;
using System.Diagnostics;

namespace TechnicalAnalysisEngine.Tests
{
    [TestClass]
    public class TestRSI
    {
        List<double> input;
        List<double> expectedValues;

        int periods;
        int expectedOffset;

        [TestInitialize]
        public void Initialize()
        {
            input = new List<double>()
            {
                44.34, 44.09, 44.15, 43.61, 44.33, 44.83, 45.10, 45.42, 45.84, 46.08, 45.89, 46.03, 45.61, 46.28,
                46.28, 46.00, 46.03, 46.41, 46.22, 45.64, 46.21, 46.25,45.71, 46.45, 45.78, 45.35, 44.03,
                44.18, 44.22, 44.57, 43.42, 42.66, 43.13
            };

            expectedValues = new List<double>()
            {
                70.53, 66.32,66.55,69.41,66.36,57.97,62.93,63.26,56.06,62.38,54.71,50.42,39.99,41.46,41.87,45.46,37.30,33.08,37.77
            };

            periods = 14;
            expectedOffset = 13;
        }

        [TestMethod]
        public void TestRSIResultCount()
        {
            var result = AnalysisEngine.RSI(input, periods);
            
            Assert.AreEqual(expectedOffset, result.StartIndexOffset, "Start index is " + result.StartIndexOffset);
            Assert.AreEqual(expectedValues.Count, result.Values.Count, "Number of returned values is incorrect");
        }
        
        [TestMethod]
        public void TestRSIValues()
        {
            var result = AnalysisEngine.RSI(input, periods);
            bool testResult = true;

            for (int i = 0; i < expectedValues.Count; i++)
            {
                if ((int)(result.Values[i]) != (int)(expectedValues[i]))
                {
                    if (!TestHelpers.EqualsWithTolerance(result.Values[i], expectedValues[i], 1)) // 1% tolerance from expected results
                    {
                        testResult = false;
                        break;
                    }
                }
            }

            Assert.IsTrue(testResult);
        }

        [TestMethod]
        public void TestRSIPerformance()
        {
            var output = new List<double>();

            Random random = new Random();
            var randomlyGeneratedValues = new List<double>();

            for (int i = 0; i < 10000; i++)
            {
                randomlyGeneratedValues.Add(random.Next(85, 90));
            }

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            var result = AnalysisEngine.RSI(randomlyGeneratedValues, periods);

            stopWatch.Stop();
            Console.WriteLine(string.Format("RSI, {0} values, {1} μs", randomlyGeneratedValues.Count, stopWatch.ElapsedTicks / 10));
        }
    }
}
